package com.example.yunbiji0314.controller;


import com.aliyun.oss.OSSClient;
import com.example.yunbiji0314.pojo.TPermission;
import com.example.yunbiji0314.pojo.TRole;
import com.example.yunbiji0314.pojo.User;
import com.example.yunbiji0314.service.TPermissionService;
import com.example.yunbiji0314.service.TRoleService;
import com.example.yunbiji0314.service.UserService;
import com.example.yunbiji0314.util.*;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("user")
@Api(tags = "用户管理")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("register")
    @ApiOperation(value = "用户注册")
    public Result register(@RequestBody User user) {
        System.out.println(user);
        int register = userService.register(user);
        if (register > 0) {
            return new Result(Code.GET_OK, "注册成功");
        } else {
            return new Result(Code.GET_ERR, "注册失败");
        }
    }

    // redis
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    // 角色
    @Autowired
    private TRoleService tRoleService;
    // 权限
    @Autowired
    private TPermissionService tPermissionService;

    @PostMapping("login")
    @ApiOperation(value = "用户登录")
    public Result login(@RequestBody User user){
        System.out.println(user);
        // 根据用户名去数据库中查找这个用户名是否存在
        User login = userService.login(user);
        System.out.println(login);
        if (login != null) {
            // 用户名存在    前端传递过来的密码是明文 数据库是加密的 所以我们需要进行一下比对
            String encrypt = Md5Util.encrypt(user.getPassword());
            if(login.getPassword().equals(encrypt)){
//                 用户名也对 密码也对
//                 我们需要把这个人拥有的权限和角色查询回来 放到redis当中  为了后续spring security认证和鉴权做准备
                LoginUser loginUser = new LoginUser();
                loginUser.setName(user.getUsername());
                loginUser.setPwd(user.getPassword());  //加密的密码

                //查询这个人的角色 一个人可能有多个角色
                List<TRole> roles = tRoleService.findById(login.getId());
                //通过steam流的方式 从集合中获取到角色
                List<String> rolkeys= roles.stream().map(item->item.getKeyword()).collect(Collectors.toList());

                // 查询这个人的权限 一个人也可能有多个权限
                List<TPermission> permissions = tPermissionService.findById(login.getId());
                // 通过steam流的方式 从集合中获取到权限
                List<String> perkeys= permissions.stream().map(item->item.getKeyword()).collect(Collectors.toList());

                // 把我们角色的集合和权限的集合都塞到一起  整体把集合存放到LoginUser的相关属性中
                List<String> quanxians = new ArrayList<>();

                quanxians.addAll(rolkeys);
                quanxians.addAll(perkeys);
                //将 角色和权限的集合都放到LoginUser的集合中
                loginUser.setQuanxianandrole(quanxians);

                // 把用户名密码 角色 权限 放到redis当中
                redisTemplate.opsForValue().set(loginUser.getName(),loginUser);

                //发牌牌，生成一个JWT的字符串
                String jwt="";
                /**
                 * 第一个参数是 加密的算法  第二个参数是密钥
                 *
                 * signWith(SignatureAlgorithm.HS256,"hxzy")
                 * setIssuedAt()  设置签发时间
                 * setExpiration() 过期时间
                 */

                // 日历
                Calendar calendar = Calendar.getInstance();
                Date time = calendar.getTime();// 当前时间
                calendar.add(Calendar.HOUR,24);// 日历往后加30分钟
                Date guoqi=  calendar.getTime(); // 30分钟之后的时间
                JwtBuilder xx = Jwts.builder().setExpiration(guoqi).setIssuedAt(time).signWith(SignatureAlgorithm.HS256,"hxzy");
                Map mm = new HashMap();
                // 我们需要把登录的用户名填写在jwt的私有信息中
                mm.put("username", user.getUsername());

                xx.addClaims(mm);// jwt第二个部分中有一个私有信息

                // 通过JwtBuilder对象的compact这个方法来生成JWT字符串
                jwt =xx.compact();
                System.out.println(jwt);

                // 当我们需要向前端响应多个数据时  直接用Map
                Map ms = new HashMap();
                ms.put("duixiang",login);
                ms.put("token",jwt);


                return new Result(Code.GET_OK, ms,"登录成功");
            }else {
                return new Result(Code.GET_ERR, "密码输入错误");
            }
        }else {
            return new Result(Code.GET_ERR, "请先注册");
        }
    }

    @Autowired
    private OssUtil ossUtil;

    @RequestMapping("/upload")
    public Result upload(MultipartFile file) throws IOException {
        //获取客户端上传过来的文件名
        String filename = file.getOriginalFilename();
        System.out.println("旧文件名："+filename);
        //为了防止客户端传递过来的文件名重复 我们使用uuid重命名
        String newname = UUID.randomUUID().toString().substring(24)+"-"+filename;
        System.out.println("新文件名："+newname);
        //我们的后端此时就会收到前端传递过来的文件
        //我们后端程序就可以选择把文件 放在oss-cn-beijing.aliyuncs.com 服务器上的 upload-0219 桶里
        /**
         * 第一个参数 域名 记得域名前面要加https://
         * 第二个参数  ID
         * 第三个参数 密钥
         */
        OSSClient ossClient = new OSSClient(ossUtil.getUrl(), ossUtil.getId(), ossUtil.getMiyou());
        /**
         * xx调用putObject把文件存放到桶里面
         * 第一个参数 桶名
         * 第二个参数 新文件的名字
         * 第三个参数 客户端上传文件的字节流
         */
        ossClient.putObject(ossUtil.getTong(),newname,file.getInputStream());
        /**
         * https://upload-0219.oss-cn-beijing.aliyuncs.com/30846c2f36ab-tu01.png
         */
        //url=https://oss-cn-beijing.aliyuncs.com
        //获取域名
        String url01=ossUtil.getUrl();
        //分割域名
        String[] split = url01.split("//");
        System.out.println(split[0]);
        System.out.println(split[1]);
        String url=split[0]+"//"+ossUtil.getTong()+"."+split[1]+"/"+newname;
        return new Result(Code.UPLOAD_OK,url, "上传成功");
    }

    @PostMapping("/saveupload")
    @ApiOperation(value = "保存上传头像")
    public Result saveupload(@RequestBody User user){
        System.out.println(user);
        int i = userService.saveupload(user);
        if (i>0){
            return new Result(Code.SAVE_OK,"保存成功");
        }else {
            return new Result(Code.SAVE_ERR, "保存失败");
        }
    }

    @PostMapping("/password")
    @ApiOperation(value = "修改密码")
    public Result password(@RequestBody User user){
        int savepassword = userService.savepassword(user);
        if (savepassword>0){
            return new Result(Code.SAVE_OK,"修改成功");
        }else {
            return new Result(Code.SAVE_ERR, "修改失败");
        }
    }

    @PostMapping("/saveinfo")
    @ApiOperation(value = "修改个人信息")
    public Result saveinfo(@RequestBody User user){
        int saveinfo = userService.saveinfo(user);
        if (saveinfo>0){
            return new Result(Code.SAVE_OK,"修改成功");
        }else {
            return new Result(Code.SAVE_ERR, "修改失败");
        }
    }
}
